package com.chinameyer.equipment_ebook.util;

import com.chinameyer.equipment_ebook.bo.MyDefineBO;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

/**
 * @Author meyer@HongYe
 */
@Component
public class ZipUtil {


    @Autowired
    private MyDefineBO myDefineBO;
    /**
     * 从OSS服务中下载所需文件到本地临时文件，并将文件以ZIP格式进行压缩
     * @param zipName zip文件名
     * @throws Exception
     */
    public String fileToZip(String fileName, String zipName){
        File file = null;
        String zipUrl = null;
        try{
            //获取待压缩文件源
            file = new File(fileName);
            //指定压缩文件存放路径
            String basePath=new File(this.getClass().getResource("/").getPath()) +"/static/zipFiles/";
            String  zipFileName = basePath+zipName+".zip";
            File fileTemp = new File(basePath);
            if (!fileTemp.exists()){
                fileTemp.mkdirs();
            }
            File zipFile = new File(zipFileName);
            //构建输出流
            FileOutputStream fout = new FileOutputStream(zipFile);
            //构建压缩输出流
            ArchiveOutputStream aos = new ArchiveStreamFactory().createArchiveOutputStream(ArchiveStreamFactory.ZIP, fout);
            //判断获取的压缩实例是否为zip格式
            if (aos instanceof ZipArchiveOutputStream){
                //进行压缩实例强转
                ZipArchiveOutputStream zipos = (ZipArchiveOutputStream) aos;

                //将指定文件封装成压缩项，添加到压缩流中
                //判断文件是否存在
                if (file.exists()){
                    //判断文件类型，调用文件处理方法
                    zipDir(zipos,file,"");
                }
            }
            //关闭流
            aos.flush();
            aos.close();
            zipUrl = "http://"+myDefineBO.getDomain1()+"/zipFiles/"+zipName+".zip";
            String filePath = file.getPath()+"/"+zipName;
            file = new File(filePath);
        }catch (Exception e){
            System.out.println(e.getMessage());
            e.printStackTrace();
        }finally {
            //删除文件源，只保留zip文件
            if (file.exists()){
                //判断文件类型
                if(file.isDirectory()){
                    //对文件夹进行处理递归删除（有内容的文件夹不能直接被删除）
                    deleteFile(file);
                    file.delete();//删除空文件夹
                }else {
                    file.delete();//文件直接删除
                }
            }
        }
        return zipUrl;
    }


    /**
     * 对压缩文件夹进行循环处理
     * @param zipos 压缩流
     * @param file 要处理的文件
     * @param baseDir 要处理的文件的文件夹路径
     * @throws IOException
     */
    private void zipDir(ZipArchiveOutputStream zipos,File file,String baseDir) throws IOException {
        if (file.isDirectory()){
            File[] files = file.listFiles();
            for (File f:files){
                //对文件进行递归判断
                zipDir(zipos,f,baseDir+file.getName()+File.separator);
            }
        }else{
            //将文件封装成压缩项
            //根据文件创建zip内容实体
            ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(file,baseDir+file.getName());
            //将根据文件创建的实体保存到压缩流中
            zipos.putArchiveEntry(zipArchiveEntry);
            //将内容输出到压缩文件中
            zipos.write(FileUtils.readFileToByteArray(file));
            zipos.closeArchiveEntry();
        }
    }

    /**
     * 文件及文件夹的递归删除
     * @param file
     */
    public void deleteFile(File file){
        if (file.isDirectory()){
            File[] files = file.listFiles();
            for (File f: files){
                deleteFile(f);
                //将循环后的空文件夹删除
                if(f.exists()){
                    f.delete();
                }
            }
        }else{
            file.delete();
        }
    }
}
